#include <iostream>
#include <list>
#include <memory>
using namespace std;

class Observer
{
public:
    virtual void update(int status) = 0;
    virtual ~Observer() {};
};

class ConcreteObserverA
    : public Observer
{
public:
    ConcreteObserverA(const string &name)
        : _name(name)
    {
    }

    virtual void update(int status) override
    {
        cout << "ConcreteObserverA name " << _name << " receved :" << status << endl;
    }

private:
    string _name;
};

class ConcreteObserverB
    : public Observer
{
public:
    ConcreteObserverB(const string &name)
        : _name(name)
    {
    }

    virtual void update(int status) override
    {
        cout << "ConcreteObserverB name " << _name << " receved :" << status << endl;
    }

private:
    string _name;
};

class Subject
{
public:
    virtual void attach(Observer *) = 0;
    virtual void dettach(Observer *) = 0;
    virtual void notify() = 0;
    virtual ~Subject() {};
};

class ConcreteSubject
    : public Subject
{
public:
    virtual void attach(Observer *pobserver) override
    {
        if (pobserver)
        {
            _obList.push_back(pobserver);
        }
    }

    virtual void dettach(Observer *pobserver) override
    {
        if (pobserver)
        {
            _obList.remove(pobserver);
        }
    }

    virtual void notify() override
    {
        for (auto &ob : _obList)
        {
            ob->update(_status);
        }
    }

    void setStatus(int status)
    {
        _status = status;
    }

    int getStatus()
    {
        return _status;
    }

private:
    list<Observer *> _obList;
    int _status;
};

void test()
{
    unique_ptr<Observer> poa(new ConcreteObserverA("Lium"));
    unique_ptr<Observer> pob(new ConcreteObserverB("TianTian"));

    unique_ptr<ConcreteSubject> psub(new ConcreteSubject());

    psub->attach(poa.get());
    psub->attach(pob.get());
    psub->setStatus(10);

    psub->notify();
    cout << endl;

    psub->setStatus(30);
    psub->notify();
    cout << endl;

    psub->dettach(pob.get());
    psub->notify();
}

int main()
{
    test();

    return 0;
}